/** Test Main function 4
 *
 *  Test Main function 4. Test the easy parallel job.
 *
 *  @author : huicong
 *  @date : 2008-11-19
 *
 */

#include "BCMI_Frame.h"
#include "ParallelFrame.h"
#include "EasyParallelJob.h"
#include "EasyParallelTask.h"

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;
using namespace bcmi_frame;

class Test1 : public EasyParallelTask
{
public:
    Test1(IN STRING __myName, IN STRING __nextName)
    {
        cout << "create " << __myName << endl;
        _myName = __myName;
        _nextName = __nextName;
        _count = 0;
    }

    ~Test1()
    {
    }

    STRING nextTaskName() const
    {

        if ("TEST" == _myName)
        {

            if (_count == 5)
            {
                return _nextName;
            }
            else
            {
                return _taskName;// _myName;
            }
        }
        else
        {
            return _nextName;
        }
    }

    HRESULT execute()
    {
        UINT _myId = _myJob->getFrame()->getMPIProcessId();
        cout << "myId = " << _myId << " : in " << _myName << " with " << _count++ << endl;
        return H_OK;
    }

    HRESULT masterHandler()
    {
        UINT _myId = _myJob->getFrame()->getMPIProcessId();
        cout << "myId = " << _myId << " : in handler " << _myName << " with " << _count++ << endl;
        return H_OK;
    }

    HRESULT initialize()
    {
        return H_OK;
    }

    HRESULT finalize()
    {
        return H_OK;
    }

    STRING _myName;
    STRING _nextName;
    UINT _count;
};

INT main(INT argc, CHAR ** argv)
{

    ParallelFrame _frame(argc, argv);

    cout << "start " << endl;

    Test1 _test1("TEST_INITIALIZE", "TEST");
    Test1 _test("TEST", __FRAME_FIN_TASK_NAME);
    Test1 _test2("TEST_FINALIZE", __FRAME_FIN_TASK_NAME);

    UINT _npro = _frame.getMPIProcessNumber();

    cout << "There are " << _npro << " processes" << endl;

    EasyParallelJob _job;
    _frame.getJobSystem()->addJob(&_job);

    UINT _gid = _job.newGroup() - 1;
    for (UINT i = 1; i < _npro; ++i)
    {
        if (i % 2 == 1)
        {
            _job.insertGroup(i, _gid);
        }
    }
    _gid = _job.newGroup() - 1;
    for (UINT i = 1; i < _npro; ++i)
    {
        if (i % 2 == 0)
        {
            _job.insertGroup(i, _gid);
        }
    }

    _job.registerInitializeTask(&_test1);
    _job.taskRegister(_test._myName, &_test);
    _job.registerFinalizeTask(&_test2);

    _frame.execute();

    _frame.~ParallelFrame();

    return 0;
}
